package com.example.dailyrecord.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.dailyrecord.base.entity.SQLBuilder;
import com.example.dailyrecord.base.service.impl.BaseServiceImpl;
import com.example.dailyrecord.dao.RecordDao;
import com.example.dailyrecord.entity.Record;
import com.example.dailyrecord.entity.StatusCode;
import com.example.dailyrecord.service.RecordService;
import com.example.dailyrecord.util.FunctionUtils;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RecordServiceImpl extends BaseServiceImpl<Record> implements RecordService {
    @Resource
    RecordDao recordDao;

    @Override
    public StatusCode insertRequest(HttpServletRequest request, HttpServletResponse response) {
        String email = getEmail(request);
        SQLBuilder notFinished = SQLBuilder.getInstance().eq(Record.UID_COLUMN, email)
                .and().nl(Record.JSSJ_COLUMN);
        long count = countByBuilder(notFinished);
        if (count > 0) {
            return StatusCode.NOT_FINISHED;
        }
        String bz = request.getParameter(Record.BZ_NAME);
        String km = request.getParameter(Record.KM_NAME);
        Record record = Record.getInstance(email, km, bz);
        insert(record);
        return StatusCode.SUCCESS;
    }

    @Override
    public PageInfo<Record> getListRequest(HttpServletRequest request, HttpServletResponse response) {
        String email = getEmail(request);
        String kssj = request.getParameter(Record.KSSJ_NAME);
        String jssj = request.getParameter(Record.JSSJ_NAME);
        String km = request.getParameter(Record.KM_NAME);

        Record record = Record.getInstance(email, kssj, jssj, km, null);
        startPage(request);
        return PageInfo.of(recordDao.getList(record));
    }

    @Override
    public Record updateRequest(HttpServletRequest request, HttpServletResponse response) {
        String bz = request.getParameter(Record.BZ_NAME);
        String id = request.getParameter(Record.ID_NAME);
        Record record = select(id);
        record.setBz(bz);
        setFinished(record, null);
        update(record);
        return record;
    }

    @Override
    public long countRequest(HttpServletRequest request, HttpServletResponse response) {
        String unit = request.getParameter("unit");
        String end = FunctionUtils.getNowTime(),
                start = FunctionUtils.getFirstDay(unit).format(FunctionUtils.YYYYMMDDHHMMSS);
        String email = getEmail(request);
        SQLBuilder sqlBuilder = SQLBuilder.getInstance().eq(Record.UID_COLUMN, email)
                .and().gte(Record.KSSJ_COLUMN, start)
                .and().lte(Record.JSSJ_COLUMN, end);
        return countByBuilder(sqlBuilder);
    }

    @Override
    public Object fun1(HttpServletRequest request, HttpServletResponse response) {
        List<String> axis = getAxis(request);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("axis", axis);

        List<Record> list = recordDao.fun1(parse(request));
        Map<String, Record> map = list.stream()
                .collect(Collectors.toMap(Record::getBz, item -> item));

        //补充没有日期的
        Map<String, Record> resMap = new LinkedHashMap<>(axis.size());
        for (String axi : axis) {
            Record temp = map.get(axi);
            if (temp != null) {
                LocalDateTime kssjTime = FunctionUtils.parse(temp.getKssj());
                LocalDateTime jssjTime = FunctionUtils.parse(temp.getJssj());
                int kssjMinute = kssjTime.getHour() * 60 + kssjTime.getMinute();
                int jssjMinute = jssjTime.getHour() * 60 + jssjTime.getMinute();
                temp.setKssj(String.valueOf(kssjMinute));
                temp.setJssj(String.valueOf(jssjMinute));
                long l = Duration.between(kssjTime, jssjTime).get(ChronoUnit.SECONDS);
                temp.setDuration((int) l / 60);
            }
            resMap.put(axi, temp);
        }
        jsonObject.put("data", resMap.values());
        return jsonObject;
    }

    @Override
    public Object fun2(HttpServletRequest request, HttpServletResponse response) {
        List<String> axis = getAxis(request);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("axis", axis);

        List<Record> records = recordDao.fun2(parse(request));
        Map<String, List<Record>> kmMap = records.stream().collect(Collectors.groupingBy(Record::getKm));
        Set<String> kms = kmMap.keySet();
        jsonObject.put("kms", kms);

        for (Map.Entry<String, List<Record>> entry : kmMap.entrySet()) {
            List<Record> temp = entry.getValue();
            List<String> data = new ArrayList<>(axis.size());

            Map<String, Record> kssjMap = temp.stream()
                    .collect(Collectors.toMap(Record::getKssj, item -> item));
            for (String axi : axis) {
                if (kssjMap.containsKey(axi)) {
                    data.add(String.valueOf(kssjMap.get(axi).getDuration()));
                } else {
                    data.add("0");
                }
            }
            jsonObject.put(entry.getKey(), data);
        }
        return jsonObject;
    }

    @Override
    public Object fun3(HttpServletRequest request, HttpServletResponse response) {
        return recordDao.fun3(parse(request));
    }

    @Override
    public Object fun4(HttpServletRequest request, HttpServletResponse response) {
        List<String> axis = getAxis(request);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("axis", axis);

        Map<String, Record> kssjMap = recordDao.fun4(parse(request, false))
                .stream().collect(Collectors.toMap(Record::getKssj, item -> item));
        List<Integer> list = new ArrayList<>(axis.size());
        for (String axi : axis) {
            if (kssjMap.containsKey(axi)) {
                list.add(kssjMap.get(axi).getDuration());
            } else {
                list.add(0);
            }
        }

        jsonObject.put("data", list);
        return jsonObject;
    }

    @Override
    public void setFinished() {
        List<Record> list = notFinishedToday();
        LocalDateTime now = LocalDateTime.now();
        list.forEach(item -> setFinished(item, now));
        updateList(list);
    }

    private void setFinished(Record record, LocalDateTime time) {
        if (time == null) {
            time = LocalDateTime.now();
        }
        long minutes = Duration.between(FunctionUtils.parse(record.getKssj()), time).get(ChronoUnit.SECONDS) / 60;
        record.setDuration((int) minutes);
        record.setJssj(time.format(FunctionUtils.YYYYMMDDHHMMSS));
    }

    @Override
    public List<Record> notFinishedToday() {
        SQLBuilder sqlBuilder = SQLBuilder.getInstance()
                .nl(Record.JSSJ_COLUMN)
                .and().cond("left(kssj,10)", FunctionUtils.getNowDate());
        return selectList(sqlBuilder);
    }

    private Record parse(HttpServletRequest request, boolean range) {
        String email = getEmail(request);
        if (range) {
            String unit = request.getParameter("unit");
            String ends = FunctionUtils.getLastDay(unit).format(FunctionUtils.YYYYMMDDHHMMSS),
                    starts = FunctionUtils.getFirstDay(unit).format(FunctionUtils.YYYYMMDDHHMMSS);
            return Record.getInstance(email, starts, ends, null, null);
        }
        return Record.getInstance(email, null, null, null, null);
    }

    private Record parse(HttpServletRequest request) {
        return parse(request, true);
    }

    private List<String> getAxis(HttpServletRequest request) {
        String unit = request.getParameter("unit");
        LocalDateTime end = FunctionUtils.getLastDay(unit), start = FunctionUtils.getFirstDay(unit);
        List<String> res = new LinkedList<>();
        LocalDate temp = start.toLocalDate(), endDay = end.toLocalDate();
        while (temp.compareTo(endDay) <= 0) {
            res.add(temp.format(FunctionUtils.YYYYMMDD));
            temp = temp.plusDays(1);
        }
        return res;
    }
}